/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.cell;

import com.daikit.commons.shared.utils.DkStringUtils;
import com.daikit.daikit4gxt.client.ui.cell.IconButtonCell.IconAlign;
import com.daikit.daikit4gxt.client.ui.cell.IconButtonCell.IconButtonCellAppearance;
import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesBuilder;
import com.google.gwt.safecss.shared.SafeStylesUtils;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.sencha.gxt.core.client.XTemplates;
import com.sencha.gxt.core.client.dom.XElement;
import com.sencha.gxt.core.client.resources.StyleInjectorHelper;


/**
 * Default appearance for {@link IconButtonCell}
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public class IconButtonCellDefaultAppearance implements IconButtonCellAppearance
{

	@SuppressWarnings("javadoc")
	public interface IconButtonCellResources extends ClientBundle
	{
		@Source("IconButtonCell.css")
		IconButtonCellStyle style();
	}

	@SuppressWarnings("javadoc")
	public interface IconButtonCellStyle extends CssResource
	{
		String iconWrap();

		String over();

		String pressed();

		String focused();
	}

	@SuppressWarnings("javadoc")
	public interface IconButtonCellTemplates extends XTemplates
	{
		@XTemplate("<div class=\"{iconWrapClass}\">{imageHtml}</div>")
		SafeHtml icon(String iconWrapClass, SafeHtml imageHtml);

		@XTemplate("<div class=\"{iconWrapClass}\" style=\"{heightStyle}\">{imageHtml}</div>")
		SafeHtml iconWithStyles(String iconWrapClass, SafeStyles heightStyle, SafeHtml imageHtml);
	}

	protected final IconButtonCellResources resources;
	protected final IconButtonCellStyle style;
	protected final IconButtonCellTemplates templates;
	private CellIconVisiblityHandler cellIconVisiblityHandler = null;

	/**
	 * Constructor with {@link IconButtonCellResources} and {@link IconButtonCellTemplates}
	 */
	public IconButtonCellDefaultAppearance()
	{
		this(GWT.<IconButtonCellResources> create(IconButtonCellResources.class));
	}

	/**
	 * Constructor with given resources and {@link IconButtonCellTemplates}
	 * 
	 * @param resources
	 *           the resources
	 */
	public IconButtonCellDefaultAppearance(final IconButtonCellResources resources)
	{
		this(resources, GWT.<IconButtonCellTemplates> create(IconButtonCellTemplates.class));
	}

	/**
	 * Constructor
	 * 
	 * @param resources
	 *           the resources
	 * @param templates
	 *           the templates
	 */
	public IconButtonCellDefaultAppearance(final IconButtonCellResources resources, final IconButtonCellTemplates templates)
	{
		this.resources = resources;
		this.templates = templates;

		this.style = resources.style();

		StyleInjectorHelper.ensureInjected(this.style, true);
	}

	@Override
	public XElement getImageElement(final XElement parent)
	{
		return parent.selectNode("table");
	}

	@Override
	public XElement getFocusElement(final XElement parent)
	{
		return parent.getFirstChildElement().cast();
	}

	@Override
	public void onFocus(final XElement parent, final boolean focused, final NativeEvent event)
	{
		parent.setClassName(style.focused(), focused);
	}

	@Override
	public void onOver(final XElement parent, final boolean over, final NativeEvent event)
	{
		parent.setClassName(style.over(), over);
	}

	@Override
	public void onPress(final XElement parent, final boolean pressed, final NativeEvent event)
	{
		parent.setClassName(style.pressed(), pressed);
	}

	@Override
	public void setCellIconVisibilityHandler(final CellIconVisiblityHandler cellIconVisiblityHandler)
	{
		this.cellIconVisiblityHandler = cellIconVisiblityHandler;
	}

	@Override
	public CellIconVisiblityHandler getCellIconVisibilityHandler()
	{
		return cellIconVisiblityHandler;
	}

	private boolean isCellIconVisible(final Context context)
	{
		return cellIconVisiblityHandler == null || cellIconVisiblityHandler.isCellIconVisible(context);
	}

	@Override
	public void render(final IconButtonCell cell, final Context context, final String value, final SafeHtmlBuilder sb)
	{
		if (isCellIconVisible(context))
		{
			final ImageResource icon = cell.getIcon(context);
			final IconAlign iconAlign = cell.getIconAlign(context);

			final SafeStylesBuilder stylesBuilder = new SafeStylesBuilder();

			// int width = -1;

			if (cell.getWidth() != -1)
			{
				int w = cell.getWidth();
				if (w < cell.getMinWidth())
				{
					w = cell.getMinWidth();
				}
				stylesBuilder.appendTrustedString("width:" + w + "px;");
				// width = w;
			}
			else
			{

				if (cell.getMinWidth() != -1)
				{
					int length = 0;
					if (icon != null)
					{
						switch (iconAlign)
						{
							case LEFT:
							case RIGHT:
								length += icon.getWidth();
								break;
							default:
								break;
						}
					}

					if (cell.getMinWidth() > length)
					{
						stylesBuilder.appendTrustedString("width:" + cell.getMinWidth() + "px;");
						// width = cell.getMinWidth();
					}
				}
			}
			final int height = cell.getHeight();
			if (height != -1)
			{
				stylesBuilder.appendTrustedString("height:" + height + "px;");
			}

			final StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.append("<div style='");
			stringBuilder.append(new SafeStylesBuilder().toSafeStyles().asString());
			final String tooltip = cell.getTooltip(context);
			if (DkStringUtils.hasText(tooltip))
			{
				stringBuilder.append("' qtip='").append(SafeHtmlUtils.htmlEscape(tooltip));
			}
			stringBuilder.append("'>");

			sb.appendHtmlConstant(stringBuilder.toString());
			if (icon != null)
			{
				writeIcon(sb, icon, height);
			}
			sb.appendHtmlConstant("</div>");
		}
	}

	private void writeIcon(final SafeHtmlBuilder builder, final ImageResource icon, final int height)
	{
		final SafeHtml iconHtml = AbstractImagePrototype.create(icon).getSafeHtml();
		if (height == -1)
		{
			builder.append(templates.icon(style.iconWrap(), iconHtml));
		}
		else
		{
			final SafeStyles heightStyle = SafeStylesUtils.fromTrustedString("height:" + height + "px;");
			builder.append(templates.iconWithStyles(style.iconWrap(), heightStyle, iconHtml));
		}
	}

}
